﻿// <copyright file="UniqueConverter.cs" company="Microsoft Corporation">
// Copyright (c) 2008 All Right Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-03-03</date>
// <summary>A Value Converter</summary>

namespace BestBuy.ValueConverters
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Windows.Data;

    /////// <summary>
    /////// Property comparer
    /////// </summary>
    ////class PropertyComparer : IEqualityComparer<object>
    ////{
    ////    /// <summary>
    ////    /// the property info
    ////    /// </summary>
    ////    PropertyInfo property;

    ////    /// <summary>
    ////    /// Initializes a new instance of the PropertyComparer class
    ////    /// </summary>
    ////    /// <param name="property">the property info</param>
    ////    public PropertyComparer(PropertyInfo property)
    ////    {
    ////        this.property = property;
    ////    }

    ////    #region IEqualityComparer<object> Members

    ////    public bool Equals(object item1, object item2)
    ////    {
    ////        return this.GetHashCode(item1) == this.GetHashCode(item2);
    ////    }

    ////    public int GetHashCode(object obj)
    ////    {
    ////        return this.property.GetValue(obj, null).ToString().GetHashCode();
    ////    }

    ////    #endregion
    ////}

    /// <summary>
    /// A Value converter
    /// </summary>
    /// <typeparam name="T">the type in the collection</typeparam>
    public class UniqueConverter<T> : IValueConverter
    {
        #region IValueConverter Members

        /// <summary>
        /// Modifies the source data before passing it to the target for display in the UI. 
        /// </summary>
        /// <param name="value">The source data being passed to the target </param>
        /// <param name="targetType">The Type of data expected by the target dependency property.</param>
        /// <param name="parameter">An optional parameter to be used in the converter logic.</param>
        /// <param name="culture">The culture of the conversion.</param>
        /// <returns>The value to be passed to the target dependency property. </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var enumerable = value as IEnumerable<T>;

            var propertyName = parameter.ToString();

            var distinct = enumerable.Distinct(new Comparer<T>(propertyName));

            return distinct;

            ////List<T> newList = new List<object>();

            ////PropertyInfo property = null;

            ////foreach (var newItem in enumerable)
            ////{
            ////    if (property == null)
            ////    {
            ////        property = newItem.GetType().GetProperty(parameter.ToString());
            ////    }

            ////    //// var itemValue = property.GetValue(newItem, null);

            ////    if (!newList.Contains(newItem, new PropertyComparer(property)))
            ////    {
            ////        newList.Add(newItem);
            ////    }
            ////}

            ////return newList;
        }

        /// <summary>
        /// Modifies the target data before passing it to the source object. This method is called only in TwoWay bindings. 
        /// </summary>
        /// <param name="value">The target data being passed to the source.</param>
        /// <param name="targetType">The Type of data expected by the source object.</param>
        /// <param name="parameter">An optional parameter to be used in the converter logic. </param>
        /// <param name="culture">The culture of the conversion.</param>
        /// <returns>The value to be passed to the source object.</returns>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
        /// <summary>
        /// Class to compare a specific property of a class with another
        /// </summary>
        /// <typeparam name="T">the type to compare</typeparam>
        internal class Comparer<T> : IEqualityComparer<T>
        {
            /// <summary>
            /// the property name
            /// </summary>
            private string propertyName;

            /// <summary>
            /// Initializes a new instance of the Comparer class.
            /// </summary>
            /// <param name="property">the property name</param>
            public Comparer(string property)
            {
                this.propertyName = property;
            }

            #region IEqualityComparer<T> Members

            /// <summary>
            /// Compare the string values of each property
            /// </summary>
            /// <param name="x">the first object</param>
            /// <param name="y">the second object</param>
            /// <returns>true if the specified objects are equal; otherwise, false.</returns>
            public bool Equals(T x, T y)
            {
                var leftProperty = this.GetPropertyValue(x);
                var rightProperty = this.GetPropertyValue(y);

                return leftProperty == rightProperty;
            }

            /// <summary>
            /// Get the string hash code of the object
            /// </summary>
            /// <param name="obj">the type to get a hash code for</param>
            /// <returns>the hash code fo the</returns>
            public int GetHashCode(T obj)
            {
                return this.GetPropertyValue(obj).GetHashCode();
            }

            #endregion

            /// <summary>
            /// Get a property value as a string
            /// </summary>
            /// <param name="obj">the object</param>
            /// <returns>the property as a string</returns>
            private string GetPropertyValue(T obj)
            {
                return obj.GetType().GetProperty(this.propertyName).GetValue(obj, null).ToString();
            }
        }
    }
}
